package com.weixin.xplore.dao.common;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.*;
import com.weixin.xplore.dao.entity.SysSetting;
import com.weixin.xplore.dao.service.impl.SysSettingDaoServiceImpl;
import com.weixin.xplore.page.CommonPageRequest;
import com.weixin.xplore.page.OrderItem;
import com.weixin.xplore.page.PageList;
import com.weixin.xplore.page.PageRequest;
import com.weixin.xplore.utils.BeanUtil;
import jakarta.annotation.Resource;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.Setter;
import lombok.SneakyThrows;
import org.anyline.adapter.KeyAdapter;
import org.anyline.data.param.ConfigStore;
import org.anyline.data.param.init.DefaultConfigStore;
import org.anyline.entity.DataRow;
import org.anyline.entity.DataSet;
import org.anyline.entity.PageNavi;
import org.anyline.service.AnylineService;
import org.springframework.beans.factory.annotation.Qualifier;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public abstract class BaseRepository<T extends CommonEntity> {

    @Resource
    @Qualifier("anyline.service")
    protected AnylineService service;

    protected String getTableName() {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        return name;
    }

    public static <P> String getFieldName(Func1<P, ?> func) {
        String generalField = StrUtil.getGeneralField(LambdaUtil.getMethodName(func));
        return StrUtil.toUnderlineCase(generalField);

    }

    public List<T> select() {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        ConfigStore configStore = new DefaultConfigStore();
        PageRequest objects = CommonPageRequest.defaultPage();
        if (objects.getPageIs()) {
            configStore.page(objects.getCurrent(), objects.getSize());
        }
        configStore.eq("deleted", 0);
        DataSet querys = service.querys(name, configStore);
        List<T> entity = BeanUtil.convert(querys.entity(objectClass));
        if (objects.getPageIs()) {
            PageList pageList = new PageList(objects, entity);
            PageNavi pageNavi = configStore.getPageNavi();
            pageList.setTotal(pageNavi.getTotalRow());
            pageList.setSize(pageNavi.getPageRows());
            pageList.setCurrent(pageNavi.getCurPage());
            return pageList;
        }
        return entity;
    }

    protected <B extends PageRequest> List<T> page(B pageRequest) {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        ConfigStore configStore = new DefaultConfigStore();
        configStore.eq("deleted", 0);

        PageRequest objects =null;
        try {
            objects =  CommonPageRequest.defaultPage(pageRequest);
        }catch (Exception e){
            objects =pageRequest;
        }
        if (objects.getPageIs()) {
            configStore.page(objects.getCurrent(), objects.getSize());
        }
        List<OrderItem> orderItemList = objects.getOrderItemList();
        if (CollUtil.isNotEmpty(orderItemList)) {
            for (OrderItem orderItem : orderItemList) {
                String column = orderItem.getColumn();

                configStore.order(StrUtil.toUnderlineCase(column), orderItem.isAsc());
            }
        }

        DataSet querys = service.querys(name, configStore);
        List<T> entity = BeanUtil.convert(querys.entity(objectClass));
        if (objects.getPageIs()) {
            PageList pageList = new PageList(objects, entity);
            PageNavi pageNavi = configStore.getPageNavi();
            pageList.setTotal(pageNavi.getTotalRow());
            pageList.setSize(pageNavi.getPageRows());
            pageList.setCurrent(pageNavi.getCurPage());
            return pageList;
        }
        return entity;
    }

    public Boolean save(T productDO) {
        Entity annotation = AnnotationUtil.getAnnotation(productDO.getClass(), Entity.class);
        String name = annotation.name();
        String id = productDO.getId();
        Long save = null;
        if (StrUtil.isBlank(id)) {
            productDO.setId(IdUtil.getSnowflakeNextIdStr());
            productDO.setDeleted(0);
            productDO.setCreateTime(new Date());

            save = service.insert(name, productDO);
        } else {
            productDO.setModifyTime(new Date());

            save = service.save(name, productDO);

        }
        return save > 0;
    }

    public Boolean saveDataRow(DataRow productDO) {
        String tableName = getTableName();
        String id = productDO.getId();
        Long save = null;
        if (StrUtil.isBlank(id)) {
            productDO.put("id", IdUtil.getSnowflakeNextIdStr());
            productDO.put("deleted", 0);
            productDO.put("create_time", new Date());

            save = service.insert(tableName, productDO);
        } else {
            productDO.put("modify_Time", new Date());
            save = service.save(tableName, productDO);

        }
        return save > 0;
    }

    protected T getById(String productId) {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        Field[] fields = ReflectUtil.getFields(objectClass);
        String s = Arrays.stream(fields).filter(v -> {
            Id annotation1 = AnnotationUtil.getAnnotation(v, Id.class);
            return annotation1 != null;
        }).map(Field::getName).findFirst().orElse(null);
        ConfigStore configStore = new DefaultConfigStore();
        configStore.eq(s, productId);
        configStore.eq("deleted", 0);
        DataRow querys = service.query(name, configStore);
        T entity = BeanUtil.convert(querys.entity(objectClass));
        return entity;
    }

    protected List<T> listByCondition(ConfigStore configStore) {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        configStore.eq("deleted", 0);
        DataSet querys = service.querys(name, configStore);
        List<T> entity = BeanUtil.convert(querys.entity(objectClass));
        return entity;
    }

    protected Long count(ConfigStore configStore) {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        configStore.eq("deleted", 0);
        long count = service.count(name, configStore);
        return count;
    }

    @SneakyThrows
    protected T selectOne(ConfigStore configStore) {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        configStore.eq("deleted", 0);
        DataRow query = service.query(name, configStore);
        if (ObjectUtil.isNull(query)) {
            return null;
        }
        return BeanUtil.convert(query.entity(objectClass));
    }


    protected T queryById(String  id) {
        Class<?> typeArgument = ClassUtil.getTypeArgument(this.getClass());
        Class<Object> objectClass = ClassUtil.loadClass(typeArgument.getName());
        Entity annotation = AnnotationUtil.getAnnotation(objectClass, Entity.class);
        String name = annotation.name();
        ConfigStore configStore = new DefaultConfigStore();
        configStore.eq("id", id);
        configStore.eq("deleted", 0);
        DataRow query = service.query(name, configStore);
        if (ObjectUtil.isNull(query)) {
            return null;
        }
        return BeanUtil.convert(query.entity(objectClass));
    }

    public Boolean updateById(T integralRecord) {
        ConfigStore configStore = new DefaultConfigStore();
        configStore.eq("deleted", 0);
        configStore.eq("id", integralRecord.getId());

        DataRow build = DataRow.build(KeyAdapter.KEY_CASE.CAMEL_SRC, integralRecord);

        return service.update(getTableName(), build, configStore) > 0;
    }

    protected Boolean deleteById(T bySaKey) {
        ConfigStore configStore = new DefaultConfigStore();
        configStore.eq("id", bySaKey.getId());
        return service.delete(configStore) > 0;
    }
}
